bitkeeper revision 1.974.1.1 (40d1af31iUa7xgOjIcSvMJwh-WxR2g)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 17 Jun 2004 14:48:17 +0000 (14:48 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 17 Jun 2004 14:48:17 +0000 (14:48 +0000)
Cleanups.

xen/arch/x86/i8259.c
xen/arch/x86/irq.c
xen/arch/x86/pci-irq.c
xen/arch/x86/setup.c
xen/arch/x86/time.c
xen/drivers/char/keyboard.c
xen/drivers/char/serial.c
xen/include/asm-x86/irq.h
xen/include/xen/interrupt.h
xen/include/xen/irq.h
xen/include/xen/sched.h

index 58ecb12553352e2a8d0979f264803a5d358eeb44..42d8ab20287bb7836767193073089b428952705a 100644 (file)
@@ -48,7 +48,7 @@ BUILD_COMMON_IRQ()
  * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
  * (these are usually mapped to vectors 0x30-0x3f)
  */
-    BUILD_16_IRQS(0x0)
+BUILD_16_IRQS(0x0)
 
 #ifdef CONFIG_X86_IO_APIC
 /*
@@ -61,10 +61,10 @@ BUILD_COMMON_IRQ()
  *
  * (these are usually mapped into the 0x30-0xff vector range)
  */
-    BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
-    BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
-    BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
-    BUILD_16_IRQS(0xc)
+BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
+BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
+BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
+BUILD_16_IRQS(0xc)
 #endif
 
 #undef BUILD_16_IRQS
@@ -77,23 +77,21 @@ BUILD_COMMON_IRQ()
  * through the ICC by us (IPIs)
  */
 #ifdef CONFIG_SMP
-    BUILD_SMP_INTERRUPT(event_check_interrupt,EVENT_CHECK_VECTOR)
-    BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
-    BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+BUILD_SMP_INTERRUPT(event_check_interrupt,EVENT_CHECK_VECTOR)
+BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
 #endif
 
 /*
- * every pentium local APIC has two 'local interrupts', with a
+ * Every pentium local APIC has two 'local interrupts', with a
  * soft-definable vector attached to both interrupts, one of
  * which is a timer interrupt, the other one is error counter
  * overflow. Linux uses the local APIC timer interrupt to get
  * a much simpler SMP time architecture:
  */
-#ifdef CONFIG_X86_LOCAL_APIC
-    BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
-    BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
-    BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
-#endif
+BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
 
 #define IRQ(x,y) \
        IRQ##x##y##_interrupt
@@ -374,56 +372,24 @@ void __init init_8259A(int auto_eoi)
     spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
+static struct irqaction cascade = { no_action, "cascade", NULL};
 
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-
-static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
-
-void __init init_ISA_irqs (void)
+void __init init_IRQ(void)
 {
     int i;
 
-#ifdef CONFIG_X86_LOCAL_APIC
     init_bsp_APIC();
-#endif
-    init_8259A(0);
 
-    for (i = 0; i < NR_IRQS; i++) {
-        irq_desc[i].status = IRQ_DISABLED;
-        irq_desc[i].action = 0;
-        irq_desc[i].depth = 1;
-
-        if (i < 16) {
-            /*
-             * 16 old-style INTA-cycle interrupts:
-             */
-            irq_desc[i].handler = &i8259A_irq_type;
-        } else {
-            /*
-             * 'high' PCI IRQs filled in on demand
-             */
-            irq_desc[i].handler = &no_irq_type;
-        }
-    }
-}
-
-void __init init_IRQ(void)
-{
-    int i;
-
-    init_ISA_irqs();
+    init_8259A(0);
 
-    /*
-     * Cover the whole vector space, no vector can escape
-     * us. (some of these will be overridden and become
-     * 'special' SMP interrupts)
-     */
-    for (i = 0; i < NR_IRQS; i++) {
-        int vector = FIRST_EXTERNAL_VECTOR + i;
-        if (vector != HYPERVISOR_CALL_VECTOR) 
-            set_intr_gate(vector, interrupt[i]);
+    for ( i = 0; i < NR_IRQS; i++ )
+    {
+        irq_desc[i].status  = IRQ_DISABLED;
+        irq_desc[i].handler = (i<16) ? &i8259A_irq_type : &no_irq_type;
+        irq_desc[i].action  = NULL;
+        irq_desc[i].depth   = 1;
+        spin_lock_init(&irq_desc[i].lock);
+        set_intr_gate(FIRST_EXTERNAL_VECTOR+i, interrupt[i]);
     }
 
 #ifdef CONFIG_SMP
@@ -433,38 +399,26 @@ void __init init_IRQ(void)
      */
     set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
 
-    /*
-     * The reschedule interrupt is a CPU-to-CPU reschedule-helper
-     * IPI, driven by wakeup.
-     */
+    /* Various IPI functions. */
     set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
-
-    /* IPI for invalidation */
     set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
-
-    /* IPI for generic function call */
     set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
 #endif 
 
-#ifdef CONFIG_X86_LOCAL_APIC
-    /* self generated IPI for local APIC timer */
+    /* Self-generated IPI for local APIC timer. */
     set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
-    /* IPI vectors for APIC spurious and error interrupts */
+    /* IPI vectors for APIC spurious and error interrupts. */
     set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
     set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-#endif
 
-    /*
-     * Set the clock to HZ Hz, we already have a valid
-     * vector now:
-     */
+    /* Set the clock to HZ Hz */
 #define CLOCK_TICK_RATE 1193180 /* crystal freq (Hz) */
 #define LATCH (((CLOCK_TICK_RATE)+(HZ/2))/HZ)
     outb_p(0x34,0x43);         /* binary, mode 2, LSB/MSB, ch 0 */
     outb_p(LATCH & 0xff , 0x40);       /* LSB */
     outb(LATCH >> 8 , 0x40);   /* MSB */
 
-    setup_irq(2, &irq2);
+    setup_irq(2, &cascade);
 }
 
index 068085d0db32ae4a412a4449c087eecf7b8fc06e..bdb070dc636247aa6461047450235c0df942c996 100644 (file)
-/*
- *      linux/arch/i386/kernel/irq.c
- *
- *      Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
- *
- * This file contains the code used by various IRQ handling routines:
- * asking for different IRQ's should be done through these routines
- * instead of just grabbing them. Thus setup_irqs with different IRQ numbers
- * shouldn't result in any weird surprises, and installing new handlers
- * should be easier.
- */
-
-/*
- * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
- *
- * IRQs are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
+/******************************************************************************
+ * arch/x86/irq.c
+ * 
+ * Portions of this file are:
+ *  Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
  */
 
 #include <xen/config.h>
-#include <xen/init.h>
 #include <xen/errno.h>
-#include <xen/sched.h>
+#include <xen/event.h>
 #include <xen/interrupt.h>
 #include <xen/irq.h>
-#include <xen/slab.h>
-#include <xen/event.h>
-#include <asm/mpspec.h>
-#include <asm/io_apic.h>
-#include <asm/msr.h>
-#include <asm/hardirq.h>
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/flushtlb.h>
-#include <xen/delay.h>
 #include <xen/perfc.h>
+#include <xen/sched.h>
 #include <asm/smpboot.h>
 
-/*
- * Linux has a controller-independent x86 interrupt architecture.
- * every controller has a 'controller-template', that is used
- * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the apropriate
- * controller. Thus drivers need not be aware of the
- * interrupt-controller.
- *
- * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
- * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
- * (IO-APICs assumed to be messaging to Pentium local-APICs)
- *
- * the code is designed to be easily extended with new/different
- * interrupt controllers, without having to do assembly magic.
- */
-
-/*
- * Controller mappings for all interrupt sources:
- */
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
-{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned;
 
 static void __do_IRQ_guest(int irq);
 
-/*
- * Special irq handlers.
- */
-
 void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
 
-/*
- * Generic no controller code
- */
-
 static void enable_none(unsigned int irq) { }
 static unsigned int startup_none(unsigned int irq) { return 0; }
 static void disable_none(unsigned int irq) { }
 static void ack_none(unsigned int irq)
 {
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesnt deserve
- * a generic callback i think.
- */
-#if CONFIG_X86
-    printk("unexpected IRQ trap at vector %02x\n", irq);
-#ifdef CONFIG_X86_LOCAL_APIC
-    /*
-         * Currently unexpected vectors happen only on SMP and APIC.
-         * We _must_ ack these because every local APIC has only N
-         * irq slots per priority level, and a 'hanging, unacked' IRQ
-         * holds up an irq slot - in excessive cases (when multiple
-         * unexpected vectors occur) that might lock up the APIC
-         * completely.
-         */
+    printk("Unexpected IRQ trap at vector %02x.\n", irq);
     ack_APIC_irq();
-#endif
-#endif
 }
 
-/* startup is the same as "enable", shutdown is same as "disable" */
 #define shutdown_none   disable_none
 #define end_none        enable_none
 
@@ -115,420 +43,132 @@ struct hw_interrupt_type no_irq_type = {
 };
 
 atomic_t irq_err_count;
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
 atomic_t irq_mis_count;
-#endif
-#endif
-
-/*
- * Generic, controller-independent functions:
- */
-
-/*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-static int handle_IRQ_event(unsigned int irq, 
-                            struct pt_regs * regs, 
-                            struct irqaction * action)
-{
-    int status;
-    int cpu = smp_processor_id();
-
-    irq_enter(cpu, irq);
-
-    status = 1; /* Force the "do bottom halves" bit */
 
-    if (!(action->flags & SA_INTERRUPT))
-        __sti();
-
-    do {
-        status |= action->flags;
-        action->handler(irq, action->dev_id, regs);
-        action = action->next;
-    } while (action);
-
-    __cli();
-
-    irq_exit(cpu, irq);
-
-    return status;
-}
-
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock. 
- */
-/**
- *      disable_irq_nosync - disable an irq without waiting
- *      @irq: Interrupt to disable
- *
- *      Disable the selected interrupt line.  Disables and Enables are
- *      nested.
- *      Unlike disable_irq(), this function does not ensure existing
- *      instances of the IRQ handler have completed before returning.
- *
- *      This function may be called from IRQ context.
- */
 inline void disable_irq_nosync(unsigned int irq)
 {
-    irq_desc_t *desc = irq_desc + irq;
+    irq_desc_t   *desc = &irq_desc[irq];
     unsigned long flags;
 
     spin_lock_irqsave(&desc->lock, flags);
-    if (!desc->depth++) {
+
+    if ( desc->depth++ == 0 )
+    {
         desc->status |= IRQ_DISABLED;
         desc->handler->disable(irq);
     }
+
     spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-/**
- *      disable_irq - disable an irq and wait for completion
- *      @irq: Interrupt to disable
- *
- *      Disable the selected interrupt line.  Enables and Disables are
- *      nested.
- *      This function waits for any pending IRQ handlers for this interrupt
- *      to complete before returning. If you use this function while
- *      holding a resource the IRQ handler may need you will deadlock.
- *
- *      This function may be called - with care - from IRQ context.
- */
 void disable_irq(unsigned int irq)
 {
     disable_irq_nosync(irq);
-
-    if (!local_irq_count(smp_processor_id())) {
-        do {
-            barrier();
-            cpu_relax();
-        } while (irq_desc[irq].status & IRQ_INPROGRESS);
-    }
+    do { smp_mb(); } while ( irq_desc[irq].status & IRQ_INPROGRESS );
 }
 
-/**
- *      enable_irq - enable handling of an irq
- *      @irq: Interrupt to enable
- *
- *      Undoes the effect of one call to disable_irq().  If this
- *      matches the last disable, processing of interrupts on this
- *      IRQ line is re-enabled.
- *
- *      This function may be called from IRQ context.
- */
 void enable_irq(unsigned int irq)
 {
-    irq_desc_t *desc = irq_desc + irq;
+    irq_desc_t   *desc = &irq_desc[irq];
     unsigned long flags;
 
     spin_lock_irqsave(&desc->lock, flags);
-    switch (desc->depth) {
-    case 1: {
-        unsigned int status = desc->status & ~IRQ_DISABLED;
-        desc->status = status;
-        if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-            desc->status = status | IRQ_REPLAY;
+
+    if ( --desc->depth == 0 )
+    {
+        desc->status &= ~IRQ_DISABLED;
+        if ( (desc->status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING )
+        {
+            desc->status |= IRQ_REPLAY;
             hw_resend_irq(desc->handler,irq);
         }
         desc->handler->enable(irq);
-        /* fall-through */
-    }
-    default:
-        desc->depth--;
-        break;
-    case 0:
-        printk("enable_irq(%u) unbalanced from %p\n", irq,
-               __builtin_return_address(0));
     }
+
     spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- */
-asmlinkage unsigned int do_IRQ(struct pt_regs regs)
+asmlinkage void do_IRQ(struct pt_regs regs)
 {       
-    /* 
-     * We ack quickly, we don't want the irq controller
-     * thinking we're snobs just because some other CPU has
-     * disabled global interrupts (we have already done the
-     * INT_ACK cycles, it's too late to try to pretend to the
-     * controller that we aren't taking the interrupt).
-     *
-     * 0 return value means that this irq is already being
-     * handled by some other CPU. (or is disabled)
-     */
-    int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */
-    irq_desc_t *desc = irq_desc + irq;
-    struct irqaction * action;
-    unsigned int status;
+    unsigned int      irq = regs.orig_eax & 0xff;
+    irq_desc_t       *desc = &irq_desc[irq];
+    struct irqaction *action;
 
-#ifdef PERF_COUNTERS
-    int cpu = smp_processor_id();
-    u32 cc_start, cc_end;
-
-    perfc_incra(irqs, cpu);
-    rdtscl(cc_start);
-#endif
+    perfc_incrc(irqs);
 
     spin_lock(&desc->lock);
     desc->handler->ack(irq);
 
-    /*
-      REPLAY is when Linux resends an IRQ that was dropped earlier
-      WAITING is used by probe to mark irqs that are being tested
-    */
-    status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-    status |= IRQ_PENDING; /* we _want_ to handle it */
-
-    /* We hook off guest-bound IRQs for special handling. */
-    if ( status & IRQ_GUEST )
+    if ( likely(desc->status & IRQ_GUEST) )
     {
         __do_IRQ_guest(irq);
         spin_unlock(&desc->lock);
-        return 1;
+        return;
     }
 
-    /*
-     * If the IRQ is disabled for whatever reason, we cannot use the action we 
-     * have.
-     */
-    action = NULL;
-    if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-        action = desc->action;
-        status &= ~IRQ_PENDING; /* we commit to handling */
-        status |= IRQ_INPROGRESS; /* we are handling it */
-    }
-    desc->status = status;
+    desc->status &= ~IRQ_REPLAY;
+    desc->status |= IRQ_PENDING;
 
     /*
-     * If there is no IRQ handler or it was disabled, exit early. Since we set 
-     * PENDING, if another processor is handling a different instance of this 
-     * same irq, the other processor will take care of it.
+     * Since we set PENDING, if another processor is handling a different 
+     * instance of this same irq, the other processor will take care of it.
      */
-    if (!action)
+    if ( desc->status & (IRQ_DISABLED | IRQ_INPROGRESS) )
         goto out;
 
-    /*
-     * Edge triggered interrupts need to remember pending events. This applies 
-     * to any hw interrupts that allow a second instance of the same irq to 
-     * arrive while we are in do_IRQ or in the handler. But the code here only 
-     * handles the _second_ instance of the irq, not the third or fourth. So 
-     * it is mostly useful for irq hardware that does not mask cleanly in an
-     * SMP environment.
-     */
-    for (;;) {
-        spin_unlock(&desc->lock);
-        handle_IRQ_event(irq, &regs, action);
-        spin_lock(&desc->lock);
-                
-        if (!(desc->status & IRQ_PENDING))
-            break;
+    desc->status |= IRQ_INPROGRESS;
+
+    action = desc->action;
+    while ( desc->status & IRQ_PENDING )
+    {
         desc->status &= ~IRQ_PENDING;
+        irq_enter(smp_processor_id(), irq);
+        spin_unlock_irq(&desc->lock);
+        action->handler(irq, action->dev_id, &regs);
+        spin_lock_irq(&desc->lock);
+        irq_exit(smp_processor_id(), irq);
     }
+
     desc->status &= ~IRQ_INPROGRESS;
+
  out:
-    /*
-     * The ->end() handler has to deal with interrupts which got disabled 
-     * while the handler was running.
-     */
     desc->handler->end(irq);
     spin_unlock(&desc->lock);
-
-#ifdef PERF_COUNTERS
-    rdtscl(cc_end);
-
-    if ( !action || (!(action->flags & SA_NOPROFILE)) )
-    {
-        perfc_adda(irq_time, cpu, cc_end - cc_start);
-#ifndef NDEBUG
-        if ( (cc_end - cc_start) > (cpu_khz * 100) )
-            printk("Long interrupt %08x -> %08x\n", cc_start, cc_end);
-#endif
-    }
-#endif
-
-    return 1;
 }
 
-/**
- *      request_irq - allocate an interrupt line
- *      @irq: Interrupt line to allocate
- *      @handler: Function to be called when the IRQ occurs
- *      @irqflags: Interrupt type flags
- *      @devname: An ascii name for the claiming device
- *      @dev_id: A cookie passed back to the handler function
- *
- *      This call allocates interrupt resources and enables the
- *      interrupt line and IRQ handling. From the point this
- *      call is made your handler function may be invoked. Since
- *      your handler function must clear any interrupt the board 
- *      raises, you must take care both to initialise your hardware
- *      and to set up the interrupt handler in the right order.
- *
- *      Dev_id must be globally unique. Normally the address of the
- *      device data structure is used as the cookie. Since the handler
- *      receives this value it makes sense to use it.
- *
- *      If your interrupt is shared you must pass a non NULL dev_id
- *      as this is required when freeing the interrupt.
- *
- *      Flags:
- *
- *      SA_SHIRQ                Interrupt is shared
- *
- *      SA_INTERRUPT            Disable local interrupts while processing
- */
-int request_irq(unsigned int irq, 
-                void (*handler)(int, void *, struct pt_regs *),
-                unsigned long irqflags, 
-                const char * devname,
-                void *dev_id)
+void free_irq(unsigned int irq)
 {
-    int retval;
-    struct irqaction * action;
-
-    if (irq >= NR_IRQS)
-        return -EINVAL;
-    if (!handler)
-        return -EINVAL;
-
-    action = (struct irqaction *)
-        kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-    if (!action)
-        return -ENOMEM;
-
-    action->handler = handler;
-    action->flags = irqflags;
-    action->mask = 0;
-    action->name = devname;
-    action->next = NULL;
-    action->dev_id = dev_id;
-
-    retval = setup_irq(irq, action);
-    if (retval)
-        kfree(action);
-
-    return retval;
-}
-
-/**
- *      free_irq - free an interrupt
- *      @irq: Interrupt line to free
- *      @dev_id: Device identity to free
- *
- *      Remove an interrupt handler. The handler is removed and if the
- *      interrupt line is no longer in use by any driver it is disabled.
- *      On a shared IRQ the caller must ensure the interrupt is disabled
- *      on the card it drives before calling this function. The function
- *      does not return until any executing interrupts for this IRQ
- *      have completed.
- *
- *      This function may be called from interrupt context. 
- *
- *      Bugs: Attempting to free an irq in a handler for the same irq hangs
- *            the machine.
- */
-void free_irq(unsigned int irq, void *dev_id)
-{
-    irq_desc_t *desc;
-    struct irqaction **p;
+    irq_desc_t   *desc = &irq_desc[irq];
     unsigned long flags;
 
-    if (irq >= NR_IRQS)
-        return;
-
-    desc = irq_desc + irq;
     spin_lock_irqsave(&desc->lock,flags);
-    p = &desc->action;
-    for (;;) {
-        struct irqaction * action = *p;
-        if (action) {
-            struct irqaction **pp = p;
-            p = &action->next;
-            if (action->dev_id != dev_id)
-                continue;
-
-            /* Found it - now remove it from the list of entries */
-            *pp = action->next;
-            if (!desc->action) {
-                desc->status |= IRQ_DISABLED;
-                desc->handler->shutdown(irq);
-            }
-            spin_unlock_irqrestore(&desc->lock,flags);
-
-#ifdef CONFIG_SMP
-            /* Wait to make sure it's not being used on another CPU */
-            while (desc->status & IRQ_INPROGRESS) {
-                barrier();
-                cpu_relax();
-            }
-#endif
-            kfree(action);
-            return;
-        }
-        printk("Trying to free free IRQ%d\n",irq);
-        spin_unlock_irqrestore(&desc->lock,flags);
-        return;
-    }
+    desc->action  = NULL;
+    desc->depth   = 1;
+    desc->status |= IRQ_DISABLED;
+    desc->handler->shutdown(irq);
+    spin_unlock_irqrestore(&desc->lock,flags);
+
+    /* Wait to make sure it's not being used on another CPU */
+    do { smp_mb(); } while ( irq_desc[irq].status & IRQ_INPROGRESS );
 }
 
-int setup_irq(unsigned int irq, struct irqaction * new)
+int setup_irq(unsigned int irq, struct irqaction *new)
 {
-    int shared = 0;
+    irq_desc_t   *desc = &irq_desc[irq];
     unsigned long flags;
-    struct irqaction *old, **p;
-    irq_desc_t *desc = irq_desc + irq;
-
-    /*
-     * The following block of code has to be executed atomically
-     */
     spin_lock_irqsave(&desc->lock,flags);
 
-    if ( desc->status & IRQ_GUEST )
+    if ( desc->action != NULL )
     {
         spin_unlock_irqrestore(&desc->lock,flags);
         return -EBUSY;
     }
 
-    p = &desc->action;
-    if ((old = *p) != NULL) {
-        /* Can't share interrupts unless both agree to */
-        if (!(old->flags & new->flags & SA_SHIRQ)) {
-            spin_unlock_irqrestore(&desc->lock,flags);
-            return -EBUSY;
-        }
-
-        /* add new interrupt at end of irq queue */
-        do {
-            p = &old->next;
-            old = *p;
-        } while (old);
-        shared = 1;
-    }
-
-    *p = new;
-
-    if (!shared) {
-        desc->depth = 0;
-        desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
-        desc->handler->startup(irq);
-    }
+    desc->action  = new;
+    desc->depth   = 0;
+    desc->status &= ~IRQ_DISABLED;
+    desc->handler->startup(irq);
 
     spin_unlock_irqrestore(&desc->lock,flags);
 
@@ -536,7 +176,6 @@ int setup_irq(unsigned int irq, struct irqaction * new)
 }
 
 
-
 /*
  * HANDLING OF GUEST-BOUND PHYSICAL IRQS
  */
@@ -551,10 +190,10 @@ typedef struct {
 
 static void __do_IRQ_guest(int irq)
 {
-    irq_desc_t *desc = &irq_desc[irq];
+    irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
     struct task_struct *p;
-    int i;
+    int                 i;
 
     for ( i = 0; i < action->nr_guests; i++ )
     {
@@ -567,9 +206,9 @@ static void __do_IRQ_guest(int irq)
 
 int pirq_guest_unmask(struct task_struct *p)
 {
-    irq_desc_t *desc;
-    int i, j, pirq;
-    u32 m;
+    irq_desc_t    *desc;
+    int            i, j, pirq;
+    u32            m;
     shared_info_t *s = p->shared_info;
 
     for ( i = 0; i < 2; i++ )
@@ -594,10 +233,10 @@ int pirq_guest_unmask(struct task_struct *p)
 
 int pirq_guest_bind(struct task_struct *p, int irq, int will_share)
 {
-    unsigned long flags;
-    irq_desc_t *desc = &irq_desc[irq];
+    irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action;
-    int rc = 0;
+    unsigned long       flags;
+    int                 rc = 0;
 
     if ( !IS_CAPABLE_PHYSDEV(p) )
         return -EPERM;
@@ -630,7 +269,7 @@ int pirq_guest_bind(struct task_struct *p, int irq, int will_share)
         
         desc->depth = 0;
         desc->status |= IRQ_GUEST;
-        desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
+        desc->status &= ~IRQ_DISABLED;
         desc->handler->startup(irq);
 
         /* Attempt to bind the interrupt target to the correct CPU. */
@@ -662,10 +301,10 @@ int pirq_guest_bind(struct task_struct *p, int irq, int will_share)
 
 int pirq_guest_unbind(struct task_struct *p, int irq)
 {
-    unsigned long flags;
-    irq_desc_t *desc = &irq_desc[irq];
+    irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action;
-    int i;
+    unsigned long       flags;
+    int                 i;
 
     spin_lock_irqsave(&desc->lock, flags);
 
@@ -679,6 +318,7 @@ int pirq_guest_unbind(struct task_struct *p, int irq)
     {
         desc->action = NULL;
         kfree(action);
+        desc->depth   = 1;
         desc->status |= IRQ_DISABLED;
         desc->status &= ~IRQ_GUEST;
         desc->handler->shutdown(irq);
@@ -695,3 +335,26 @@ int pirq_guest_unbind(struct task_struct *p, int irq)
     spin_unlock_irqrestore(&desc->lock, flags);    
     return 0;
 }
+
+int pirq_guest_bindable(int irq, int will_share)
+{
+    irq_desc_t         *desc = &irq_desc[irq];
+    irq_guest_action_t *action;
+    unsigned long       flags;
+    int                 okay;
+
+    spin_lock_irqsave(&desc->lock, flags);
+
+    action = (irq_guest_action_t *)desc->action;
+
+    /*
+     * To be bindable the IRQ must either be not currently bound (1), or
+     * it must be shareable (2) and not at its share limit (3).
+     */
+    okay = ((!(desc->status & IRQ_GUEST) && (action == NULL)) || /* 1 */
+            (action->shareable && will_share &&                  /* 2 */
+             (action->nr_guests != IRQ_MAX_GUESTS)));            /* 3 */
+
+    spin_unlock_irqrestore(&desc->lock, flags);
+    return okay;
+}
index 0a6b84c9babe021e869989af8cec51b228f71553..a99bca1617c7fbaa1ffb6e702e018fe705516e64 100644 (file)
@@ -903,10 +903,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
                        if (!(mask & (1 << i)))
                                continue;
                        if (pirq_penalty[i] < pirq_penalty[newirq] &&
-                           !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
-                               free_irq(i, dev);
+                           pirq_guest_bindable(i,1))
                                newirq = i;
-                       }
                }
        }
        DBG(" -> newirq=%d", newirq);
index ba953671299ccd449a83cd526e9c3f79b05559c0..716d25800e1d8abc605b4ffb02c196d6908bfa47 100644 (file)
@@ -300,8 +300,8 @@ unsigned long pci_mem_start = 0x10000000;
 
 void __init start_of_day(void)
 {
-    extern void trap_init(void);
     extern void init_IRQ(void);
+    extern void trap_init(void);
     extern void time_init(void);
     extern void ac_timer_init(void);
     extern void initialize_keytable(); 
@@ -350,8 +350,8 @@ void __init start_of_day(void)
         get_smp_config();
 #endif
     scheduler_init();  
-    trap_init();
     init_IRQ();  /* installs simple interrupt wrappers. Starts HZ clock. */
+    trap_init();
     time_init(); /* installs software handler for HZ clock. */
     softirq_init();
     init_apic_mappings(); /* make APICs addressable in our pagetables. */
index 092bb78765dcd94e087e8f6d3a82b187df0579ed..4cfc992b82c1e005a9baa0ab9c669630be958494 100644 (file)
@@ -54,7 +54,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     u64 full_tsc;
 
-    write_lock(&time_lock);
+    write_lock_irq(&time_lock);
 
 #ifdef CONFIG_X86_IO_APIC
     if ( timer_ack ) 
@@ -89,15 +89,14 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     /* Updates system time (nanoseconds since boot). */
     stime_irq += MILLISECS(1000/HZ);
 
-    write_unlock(&time_lock);
+    write_unlock_irq(&time_lock);
 
     /* Rough hack to allow accurate timers to sort-of-work with no APIC. */
     if ( do_timer_lists_from_pit )
         __cpu_raise_softirq(smp_processor_id(), AC_TIMER_SOFTIRQ);
 }
 
-static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0,
-                                  "timer", NULL, NULL};
+static struct irqaction irq0 = { timer_interrupt, "timer", NULL};
 
 /* ------ Calibrate the TSC ------- 
  * Return processor ticks per second / CALIBRATE_FRAC.
index e736aa737f55a80a2e13e33e65a7b698b4c8d99b..7e4391351e9f4247e5f7a40861c4c57a403c2046 100644 (file)
@@ -13,6 +13,7 @@
 #include <hypervisor-ifs/kbd.h>
 #include <xen/event.h>
 #include <xen/console.h>
+#include <xen/interrupt.h>
 
 /* Hash-defines torn from <xen/pc_keyb.h> and <asm/keyboard.h> */
 
@@ -241,23 +242,13 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
     
     
+static struct irqaction keyb = { keyboard_interrupt, "Keyboard",   NULL };
+static struct irqaction aux  = { keyboard_interrupt, "PS/2 Mouse", NULL };
 
 void initialize_keyboard()
 {
     spin_lock_init(&kbd_lock);
-
-    if( request_irq(KEYBOARD_IRQ, keyboard_interrupt, 
-                    SA_NOPROFILE, "keyboard", NULL)) 
-    {
-        printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); 
-        return;
-    }
-
-    if ( request_irq(AUX_IRQ, keyboard_interrupt, 
-                     SA_NOPROFILE, "PS/2 Mouse", NULL)) 
-    {
-        printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ); 
-        return;
-    }
+    (void)setup_irq(KEYBOARD_IRQ, &keyb);
+    (void)setup_irq(AUX_IRQ,      &aux);
 }
 
index 8e6cd462b882e7215f9e57710da7f27a8cda09ab..499f852fdae9004655c3e5cd0bbde89ad5296882 100644 (file)
@@ -12,6 +12,7 @@
 #include <xen/sched.h>
 #include <xen/keyhandler.h> 
 #include <xen/reboot.h>
+#include <xen/interrupt.h>
 #include <xen/irq.h>
 #include <xen/serial.h>
 #include <asm/pdb.h>
 #define RXBUFSZ 32
 #define MASK_RXBUF_IDX(_i) ((_i)&(RXBUFSZ-1))
 typedef struct {
-    int           baud, data_bits, parity, stop_bits, io_base, irq;
-    serial_rx_fn  rx_lo, rx_hi, rx;
-    spinlock_t    lock;
-    unsigned char rxbuf[RXBUFSZ];
-    unsigned int  rxbufp, rxbufc;
+    int              baud, data_bits, parity, stop_bits, io_base, irq;
+    serial_rx_fn     rx_lo, rx_hi, rx;
+    spinlock_t       lock;
+    unsigned char    rxbuf[RXBUFSZ];
+    unsigned int     rxbufp, rxbufc;
+    struct irqaction irqaction;
 } uart_t;
 
 static uart_t com[2] = {
@@ -249,12 +251,10 @@ static void uart_config_stage2(uart_t *uart)
     if ( !UART_ENABLED(uart) )
         return;
 
-    rc = request_irq(uart->irq, 
-                     serial_interrupt, 
-                     SA_NOPROFILE, 
-                     "serial", 
-                     uart);
-    if ( rc != 0 )
+    uart->irqaction.handler = serial_interrupt;
+    uart->irqaction.name    = "serial";
+    uart->irqaction.dev_id  = uart;
+    if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
         printk("ERROR: Failed to allocate serial IRQ %d\n", uart->irq);
 
     /* For sanity, clear the receive FIFO. */
index 2c7c67a0dacda7d3200e337ba2b86f60e17ea716..14d72d9eba7e7dd16ed41da0f5c3c124ef037927 100644 (file)
@@ -6,14 +6,6 @@
 #include <xen/config.h>
 #include <asm/atomic.h>
 
-#define SA_INTERRUPT    0x20000000
-#define SA_SHIRQ        0x04000000
-#define SA_NOPROFILE   0x02000000
-
-#define SA_SAMPLE_RANDOM  0   /* Linux driver compatibility */
-
-#define TIMER_IRQ 0
-
 extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
 extern void enable_irq(unsigned int);
@@ -34,12 +26,6 @@ extern void enable_irq(unsigned int);
 
 /*
  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
- *
- *  some of the following vectors are 'rare', they are merged
- *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
- *  TLB, reschedule and local APIC vectors are performance-critical.
- *
- *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
  */
 #define SPURIOUS_APIC_VECTOR   0xff
 #define ERROR_APIC_VECTOR      0xfe
@@ -186,7 +172,7 @@ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
        "jmp common_interrupt");
 
 extern unsigned long prof_cpu_mask;
-extern unsigned int * prof_buffer;
+extern unsigned int *prof_buffer;
 extern unsigned long prof_len;
 extern unsigned long prof_shift;
 
index 73545a75f8f6f12dc580165a22840f7e158ecdad..193c8c394b404c5892cfc42c71be6898f26799c0 100644 (file)
 
 struct irqaction {
     void (*handler)(int, void *, struct pt_regs *);
-    unsigned long flags;
-    unsigned long mask;
     const char *name;
     void *dev_id;
-    struct irqaction *next;
 };
 
 #include <asm/hardirq.h>
index 34f54862bd39b64d54e0253159d8ebd9b95989a6..2513c59e607b31b31f46a2a78d721320f5ed84ab 100644 (file)
@@ -12,9 +12,7 @@
 #define IRQ_DISABLED   2       /* IRQ disabled - do not enter! */
 #define IRQ_PENDING    4       /* IRQ pending - replay on enable */
 #define IRQ_REPLAY     8       /* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT 16      /* IRQ is being autodetected */
-#define IRQ_WAITING    32      /* IRQ not yet seen - for autodetection */
-#define IRQ_GUEST       64      /* IRQ is handled by guest OS(es) */
+#define IRQ_GUEST       16      /* IRQ is handled by guest OS(es) */
 
 /*
  * Interrupt controller descriptor. This is all we need
@@ -53,6 +51,7 @@ typedef struct {
 extern irq_desc_t irq_desc[NR_IRQS];
 
 extern int setup_irq(unsigned int, struct irqaction *);
+extern void free_irq(unsigned int);
 
 extern hw_irq_controller no_irq_type;
 extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
@@ -61,5 +60,6 @@ struct task_struct;
 extern int pirq_guest_unmask(struct task_struct *p);
 extern int pirq_guest_bind(struct task_struct *p, int irq, int will_share);
 extern int pirq_guest_unbind(struct task_struct *p, int irq);
+extern int pirq_guest_bindable(int irq, int will_share);
 
 #endif /* __XEN_IRQ_H__ */
index 1eb0aa8bdade6867d1286418e330da420e92afe7..c0902b97d7ccbfa2f219f547ec1e62082dddbf28 100644 (file)
@@ -242,12 +242,6 @@ void new_thread(struct task_struct *p,
                 unsigned long start_stack,
                 unsigned long start_info);
 
-/* Linux puts these here for some reason! */
-extern int request_irq(unsigned int,
-                       void (*handler)(int, void *, struct pt_regs *),
-                       unsigned long, const char *, void *);
-extern void free_irq(unsigned int, void *);
-
 extern unsigned long wait_init_idle;
 #define init_idle() clear_bit(smp_processor_id(), &wait_init_idle);